package edu.upenn.cis.cis555.webserver;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.Socket;
import java.security.Principal;
import java.security.SecureRandom;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.regex.Pattern;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;

public class HttpServletRequest implements javax.servlet.http.HttpServletRequest {
	
	private static final String BASIC_AUTH = "BASIC";
	
	private HashMap<String, ArrayList<String>> m_params;
	private HashMap<String, Object> m_props;
	private HttpSession m_session;
	private String m_method;
	private StringBuffer m_requestURI;
	private Socket m_connectionsocket;
	private String m_line1;
	private HashMap<String,ArrayList<String>> m_reqHeaders;
	private Vector<Cookie> m_cookies;
	private String m_url_matched;
	private boolean m_patternMatched;
	private String char_encoding;
	
	HttpServletRequest(HttpSession session, StringBuffer requestURI, 
			Socket connectionsocket, String line1, HashMap<String,ArrayList<String>> reqHeaders, 
			String method, Vector<Cookie> cookies, String url_matched, boolean patternMatched) {
		m_session = session;
		m_requestURI = requestURI;
		m_connectionsocket = connectionsocket;
		m_line1 = line1;
		m_reqHeaders = reqHeaders;
		m_method = method;
		m_cookies = cookies;
		m_url_matched = url_matched;
		m_patternMatched = patternMatched;
		m_props = new HashMap<String, Object>();
		m_params = new HashMap<String,ArrayList<String>>();
		char_encoding = "ISO-8859-1";
	}
	
	void setMethod(String method) {
		m_method = method;
	}
	
	void setParameter(String key, String value) {
		ArrayList<String> temp = new ArrayList<String>();
		temp.add(value);
		if (!m_params.containsKey(key)) {
			m_params.put(key, temp);
		}
		else {
			m_params.get(key).add(value);
		}
	}
	
	void clearParameters() {
		m_params.clear();
	}
	
	boolean hasSession() {
		return ((m_session != null) && m_session.isValid());
	}

	@Override //DONE
	public String getAuthType() {
		// ALWAYS RETURN BASIC AUTH("BASIC")
		return BASIC_AUTH;
	}

	@Override //DONE
	public String getContextPath() {
//	    Returns the portion of the request URI that indicates the context of the request. The context path always comes first in a 
//	    request URI. The path starts with a "/" character but does not end with a "/" character. For servlets in the default (root) 
//	    context, this method returns "". The container does not decode this string.
//
//	    Returns:
//	        a String specifying the portion of the request URI that indicates the context of the request
		// This Servlet container only supports 1 concurrent web-application
		return "";
	}

	@Override //DONE
	public Cookie[] getCookies() {
//	    Returns an array containing all of the Cookie objects the client sent with this request. This method returns null if no cookies 
//	    were sent.
//
//	    Returns:
//	        an array of all the Cookies included with this request, or null if the request has no cookies
		return m_cookies.toArray(new Cookie[m_cookies.size()]);
	}

	@Override //DONE
	public long getDateHeader(String arg0) {
//	    Returns the value of the specified request header as a long value that represents a Date object. Use this method with headers 
//	    that contain dates, such as If-Modified-Since.
//
//	    The date is returned as the number of milliseconds since January 1, 1970 GMT. The header name is case insensitive.
//
//	    If the request did not have a header of the specified name, this method returns -1. If the header can't be converted to a date, 
//	    the method throws an IllegalArgumentException.
//
//	    Parameters:
//	        name - a String specifying the name of the header 
//	    Returns:
//	        a long value representing the date specified in the header expressed as the number of milliseconds since January 1, 1970 GMT, 
//	        or -1 if the named header was not included with the request 
//	    Throws:
//	        java.lang.IllegalArgumentException - If the header value can't be converted to a date
		
		//Sat, 29 Oct 1994 19:43:31 GMT
		SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
		try {
			Date d1 = format.parse(m_reqHeaders.get(arg0.toLowerCase()).get(0));
			if (m_reqHeaders.get(arg0.toLowerCase()) == null)
				return -1;
			else
				return d1.getTime();
		} catch (ParseException e) {
			throw new IllegalArgumentException();
		}
	}

	@Override //DONE
	public String getHeader(String arg0) {
//	    Returns the value of the specified request header as a String. If the request did not include a header of the specified name, 
//	    this method returns null. If there are multiple headers with the same name, this method returns the first head in the request. 
//	    The header name is case insensitive. You can use this method with any request header.
//
//	    Parameters:
//	        name - a String specifying the header name 
//	    Returns:
//	        a String containing the value of the requested header, or null if the request does not have a header of that name
		if (m_reqHeaders.get(arg0.toLowerCase()) == null)
			return null;
		else
			return m_reqHeaders.get(arg0.toLowerCase()).get(0);
	}

	@Override //DONE
	public Enumeration<String> getHeaderNames() {
//	    Returns an enumeration of all the header names this request contains. If the request has no headers, this method returns an empty 
//	    enumeration.
//
//	    Some servlet containers do not allow servlets to access headers using this method, in which case this method returns null
//
//	    Returns:
//	        an enumeration of all the header names sent with this request; if the request has no headers, an empty enumeration; if the 
//	        servlet container does not allow servlets to use this method, null
		if (m_reqHeaders == null || m_reqHeaders.keySet().size() == 0)
			return null;
		else {
			return Collections.enumeration(m_reqHeaders.keySet());
		}
	}

	@Override //DONE
	public Enumeration<String> getHeaders(String arg0) {
//	    Returns all the values of the specified request header as an Enumeration of String objects.
//
//	    Some headers, such as Accept-Language can be sent by clients as several headers each with a different value rather than sending 
//	    the header as a comma separated list.
//
//	    If the request did not include any headers of the specified name, this method returns an empty Enumeration. The header name is 
//	    case insensitive. You can use this method with any request header.
//
//	    Parameters:
//	        name - a String specifying the header name 
//	    Returns:
//	        an Enumeration containing the values of the requested header. If the request does not have any headers of that name return 
//	        an empty enumeration. If the container does not allow access to header information, return null
		if (m_reqHeaders == null || m_reqHeaders.keySet().size() == 0)
			return null;
		Set<String> empty_set = new HashSet<String>();
		if (!m_reqHeaders.containsKey(arg0.toLowerCase())) {
			return Collections.enumeration(empty_set);
		}
		else {
			return Collections.enumeration(m_reqHeaders.get(arg0.toLowerCase()));
		}
	}

	@Override //DONE
	public int getIntHeader(String arg0) {
//	    Returns the value of the specified request header as an int. If the request does not have a header of the specified name, this 
//	    method returns -1. If the header cannot be converted to an integer, this method throws a NumberFormatException.
//
//	    The header name is case insensitive.
//
//	    Parameters:
//	        name - a String specifying the name of a request header 
//	    Returns:
//	        an integer expressing the value of the request header or -1 if the request doesn't have a header of this name 
//	    Throws:
//	        java.lang.NumberFormatException - If the header value can't be converted to an int
		
		if (!m_reqHeaders.containsKey(arg0.toLowerCase())) {
			return -1;
		}
		else {
			// Assume for headers with multiple values, use the first seen
			try {
				int i = Integer.parseInt(m_reqHeaders.get(arg0.toLowerCase()).get(0));
				return i;
			}
			catch (NumberFormatException nfe)
			{
				throw new NumberFormatException();
			}
		}
	}

	@Override //DONE
	public String getMethod() {
//	    Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT. Same as the value of 
//	    the CGI variable REQUEST_METHOD.
//
//	    Returns:
//	        a String specifying the name of the method with which this request was made
		return m_method;
	}

	@Override //DONE
	public String getPathInfo() {
		// ALWAYS RETURN THE REMAINDER OF THE URL REQUEST AFTER THE PORTION MATCHED BY THE URL-PATTERN IN WEB-XML.
		// IT STARTS WITH A "/"
//	    Returns any extra path information associated with the URL the client sent when it made this request. The extra path information 
//	    follows the servlet path but precedes the query string and will start with a "/" character.
//
//	    This method returns null if there was no extra path information.
//
//	    Same as the value of the CGI variable PATH_INFO.
//
//	    Returns:
//	        a String, decoded by the web container, specifying extra path information that comes after the servlet path but before the 
//	        query string in the request URL; or null if the URL does not have any extra path information
		
		// Assignment does not want the query string included
		StringBuffer rURI = new StringBuffer(m_requestURI);
		if (rURI.toString().equals(m_url_matched))
			return null;
		StringBuffer temp = rURI.replace(0, m_url_matched.length(), "");
		if (!temp.toString().startsWith("/"))
			temp.insert(0, "/");
		return temp.toString();
	}

	@Override //DONE
	public String getQueryString() {
		// Should return the HTTP GET query string, i.e., the portion after the "?" when a GET form is posted.
//	    Returns the query string that is contained in the request URL after the path. This method returns null if the URL does not have a 
//	    query string. Same as the value of the CGI variable QUERY_STRING.
//
//	    Returns:
//	        a String containing the query string or null if the URL contains no query string. The value is not decoded by the container.
		StringBuffer rURI = new StringBuffer(m_requestURI);
		if (!rURI.toString().contains("?"))
			return null;
		Pattern p = Pattern.compile("?", Pattern.LITERAL);;
		String[] result = p.split(rURI.toString());
		return result[1];
	}

	@Override //DONE
	public String getRemoteUser() {
//	    Returns the login of the user making this request, if the user has been authenticated, or null if the user has not been 
//	    authenticated. Whether the user name is sent with each subsequent request depends on the browser and type of authentication. 
//	    Same as the value of the CGI variable REMOTE_USER.
//
//	    Returns:
//	        a String specifying the login of the user making this request, or null if the user login is not known
		return null;
	}

	@Override //DONE
	public String getRequestURI() {
//	    Returns the part of this request's URL from the protocol name up to the query string in the first line of the HTTP request. 
//	    The web container does not decode this String. For example:
//	    First line of HTTP request 	Returned Value
//	    POST /some/path.html HTTP/1.1		/some/path.html
//	    GET http://foo.bar/a.html HTTP/1.0 		/a.html
//	    HEAD /xyz?a=b HTTP/1.1		/xyz
//
//	    To reconstruct an URL with a scheme and host, use HttpUtils.getRequestURL(javax.servlet.http.HttpServletRequest).
//
//	    Returns:
//	        a String containing the part of the URL from the protocol name up to the query string
		StringBuffer rURI = new StringBuffer(m_requestURI);
		if (getQueryString() != null)
			return rURI.replace(rURI.indexOf(getQueryString())-1, rURI.length(), "").toString();
		return rURI.toString();
	}

	@Override //DONE
	public StringBuffer getRequestURL() {
//	    Reconstructs the URL the client used to make the request. The returned URL contains a protocol, server name, port number, and 
//	    server path, but it does not include query string parameters.
//
//	    Because this method returns a StringBuffer, not a string, you can modify the URL easily, for example, to append query parameters.
//
//	    This method is useful for creating redirect messages and for reporting errors.
//
//	    Returns:
//	        a StringBuffer object containing the reconstructed URL
		String scheme = getScheme();             // http
	    String serverName = getServerName();     // hostname.com
	    int serverPort = getServerPort();        // 80
	    String contextPath = getContextPath();   // /mywebapp
	    String servletPath = getServletPath();   // /servlet/MyServlet
	    String pathInfo = getPathInfo();         // /a/b;c=123

	    String url = scheme+"://"+serverName+":"+serverPort+contextPath+servletPath;
	    if (pathInfo != null)
	        url += pathInfo;
	    StringBuffer temp = new StringBuffer(url);
	    return temp;
	}

	@Override //DONE
	public String getRequestedSessionId() {
//	    Returns the session ID specified by the client. This may not be the same as the ID of the current valid session for this request. 
//	    If the client did not specify a session ID, this method returns null.
//
//	    Returns:
//	        a String specifying the session ID, or null if the request did not specify a session ID
		if (m_session == null)
			return null;
		return m_session.getId();
	}

	@Override //DONE
	public HttpSession getSession() {
//	    Returns the current session associated with this request, or if the request does not have a session, creates one.
//
//	    Returns:
//	        the HttpSession associated with this request
		return getSession(true);
	}

	@Override //DONE
	public HttpSession getSession(boolean arg0) {
//	    Returns the current HttpSession associated with this request or, if there is no current session and create is true, returns a 
//	    new session.
//
//	    If create is false and the request has no valid HttpSession, this method returns null.
//
//	    To make sure the session is properly maintained, you must call this method before the response is committed. If the container 
//	    is using cookies to maintain session integrity and is asked to create a new session when the response is committed, an 
//	    IllegalStateException is thrown.
//
//	    Parameters:
//	        create - true to create a new session for this request if necessary; false to return null if there's no current session 
//	    Returns:
//	        the HttpSession associated with this request or null if create is false and the request has no valid session
		if (arg0) {
			if (! hasSession()) {
				SecureRandom random = new SecureRandom();
				String sid = new BigInteger(130, random).toString(32);
				m_session = new HttpSession(sid);
				HttpServer.sessions.add(m_session);
			}
		} 
		else {
			if (! hasSession()) {
				HttpServer.sessions.remove(m_session);
				m_session = null;
			}
		}
		return m_session;
	}

	@Override //DONE
	public boolean isRequestedSessionIdFromCookie() {
//	    Checks whether the requested session ID came in as a cookie.
//
//	    Returns:
//	        true if the session ID came in as a cookie; otherwise, false
		return true;
	}

	@Override //DONE
	public boolean isRequestedSessionIdFromURL() {
//	    Checks whether the requested session ID came in as part of the request URL.
//
//	    Returns:
//	        true if the session ID came in as part of a URL; otherwise, false
		return false;
	}

	@Override //DONE
	public boolean isRequestedSessionIdValid() {
//	    Checks whether the requested session ID is still valid.
//
//	    Returns:
//	        true if this request has an id for a valid session in the current session context; false otherwise
		if (m_session == null)
			return false;
		return m_session.isValid();
	}

	@Override //DONE
	public Object getAttribute(String arg0) {
//	    Returns the value of the named attribute as an Object, or null if no attribute of the given name exists.
//
//	    Attributes can be set two ways. The servlet container may set attributes to make available custom information about a request. 
//	    For example, for requests made using HTTPS, the attribute javax.servlet.request.X509Certificate can be used to retrieve 
//	    information on the certificate of the client. Attributes can also be set programatically using setAttribute(java.lang.String, 
//	    		java.lang.Object). This allows information to be embedded into a request before a RequestDispatcher call.
//
//	    Attribute names should follow the same conventions as package names. This specification reserves names matching java.*, javax.*, 
//	    and sun.*.
//
//	    Parameters:
//	        name - a String specifying the name of the attribute 
//	    Returns:
//	        an Object containing the value of the attribute, or null if the attribute does not exist
		if (!m_props.containsKey(arg0))
			return null;
		return m_props.get(arg0);
	}
	
	@Override //DONE
	public String getServletPath() {
//	    Returns the part of this request's URL that calls the servlet. This path starts with a "/" character and includes either the 
//	    servlet name or a path to the servlet, but does not include any extra path information or a query string. Same as the value of 
//	    the CGI variable SCRIPT_NAME.
//
//	    This method will return an empty string ("") if the servlet used to process this request was matched using the "/*" pattern.
//
//	    Returns:
//	        a String containing the name or path of the servlet being called, as specified in the request URL, decoded, or an empty string 
//	        if the servlet used to process the request is matched using the "/*" pattern.
		if (m_patternMatched)
			return "";
		else
			return m_url_matched;
	}

	@Override //DONE
	public Enumeration<?> getAttributeNames() {
//		Returns an Enumeration containing the names of the attributes available to this request. 
//		This method returns an empty Enumeration if the request has no attributes available to it.
		return Collections.enumeration(m_props.keySet());
	}

	@Override //DONE
	public String getCharacterEncoding() {
		// Should return "ISO-8859-1" by default, and the results of setCharacterEncoding if it was previously called.
		return char_encoding;
	}

	@Override //DONE
	public int getContentLength() {
//	    Returns the length, in bytes, of the request body and made available by the input stream, or -1 if the length is not known. 
//	    For HTTP servlets, same as the value of the CGI variable CONTENT_LENGTH.
//
//	    Returns:
//	        an integer containing the length of the request body or -1 if the length is not known
		String contentlength = getHeader("content-length");
		if (contentlength == null)
			return -1;
		int i = -1;
		try {
			i = Integer.parseInt(contentlength);
		} catch (NumberFormatException nfe) {
			HttpServer.logError("Requested Content Length not Numeric");
		}
		return i;
	}

	@Override //DONE
	public String getContentType() {
//	    Returns the MIME type of the body of the request, or null if the type is not known. For HTTP servlets, same as the value of 
//	    the CGI variable CONTENT_TYPE.
//
//	    Returns:
//	        a String containing the name of the MIME type of the request, or null if the type is not known
		String contenttype = getHeader("content-type");
		if (contenttype == null)
			return null;
		return contenttype;
	}

	@Override //DONE
	public Locale getLocale() {
		// Should return null by default, or the results of setLocale if it was previously called.
		return null;
	}

	@Override //DONE
	public String getParameter(String key) {
//	    Returns the value of a request parameter as a String, or null if the parameter does not exist. Request parameters are extra 
//	    information sent with the request. For HTTP servlets, parameters are contained in the query string or posted form data.
//
//	    You should only use this method when you are sure the parameter has only one value. If the parameter might have more than one 
//	    value, use getParameterValues(java.lang.String).
//
//	    If you use this method with a multivalued parameter, the value returned is equal to the first value in the array returned by 
//	    getParameterValues.
//
//	    If the parameter data was sent in the request body, such as occurs with an HTTP POST request, then reading the body directly 
//	    via getInputStream() or getReader() can interfere with the execution of this method.
//
//	    Parameters:
//	        name - a String specifying the name of the parameter 
//	    Returns:
//	        a String representing the single value of the parameter
		if (!m_params.containsKey(key)) {
			return null;
		}
		else {
			return m_params.get(key).get(0);
		}
	}

	@Override //DONE
	public Map<String, ArrayList<String>> getParameterMap() {
//	    Returns a java.util.Map of the parameters of this request. Request parameters are extra information sent with the request. For 
//	    HTTP servlets, parameters are contained in the query string or posted form data.
//
//	    Returns:
//	        an immutable java.util.Map containing parameter names as keys and parameter values as map values. The keys in the parameter
//	        map are of type String. The values in the parameter map are of type String array.
		return m_params;
	}

	@Override //DONE
	public Enumeration<String> getParameterNames() {
//	    Returns an Enumeration of String objects containing the names of the parameters contained in this request. If the request has no 
//	    parameters, the method returns an empty Enumeration.
//
//	    Returns:
//	        an Enumeration of String objects, each String containing the name of a request parameter; or an empty Enumeration if the 
//	        request has no parameters
		Set<String> keys = m_params.keySet();
		Vector<String> atts = new Vector<String>(keys);
		return atts.elements();
	}

	@Override //DONE
	public String[] getParameterValues(String key) {
//	    Returns an array of String objects containing all of the values the given request parameter has, or null if the parameter does 
//	    not exist.
//
//	    If the parameter has a single value, the array has a length of 1.
//
//	    Parameters:
//	        name - a String containing the name of the parameter whose value is requested 
//	    Returns:
//	        an array of String objects containing the parameter's values
		if (!m_params.containsKey(key)) {
			return null;
		}
		else {
			return m_params.get(key).toArray(new String[m_params.get(key).size()]);
		}
	}

	@Override //DONE
	public String getProtocol() {
//	    Returns the name and version of the protocol the request uses in the form protocol/majorVersion.minorVersion, for example, 
//	    HTTP/1.1. For HTTP servlets, the value returned is the same as the value of the CGI variable SERVER_PROTOCOL.
//
//	    Returns:
//	        a String containing the protocol name and version number
		Pattern p = Pattern.compile(" ");
		String[] result = p.split(m_line1);
		return result[2];
	}
	
	@Override //DONE
	public String getLocalAddr() {
//	    Returns the Internet Protocol (IP) address of the interface on which the request was received.
//
//	    Returns:
//	        a String containing the IP address on which the request was received.
		return m_connectionsocket.getLocalAddress().getHostAddress();
	}

	@Override //DONE
	public String getLocalName() {
//	    Returns the host name of the Internet Protocol (IP) interface on which the request was received.
//
//	    Returns:
//	        a String containing the host name of the IP on which the request was received.
		return m_connectionsocket.getLocalAddress().getHostName();
	}

	@Override //DONE
	public int getLocalPort() {
//	    Returns the Internet Protocol (IP) port number of the interface on which the request was received.
//
//	    Returns:
//	        an integer specifying the port number
		return m_connectionsocket.getPort();
	}

	@Override //DONE
	public String getRemoteAddr() {
//	    Returns the Internet Protocol (IP) address of the client or last proxy that sent the request. For HTTP servlets, same as the 
//	    value of the CGI variable REMOTE_ADDR.
//
//	    Returns:
//	        a String containing the IP address of the client that sent the request
		return m_connectionsocket.getInetAddress().getHostAddress();
	}

	@Override //DONE
	public String getRemoteHost() {
//	    Returns the fully qualified name of the client or the last proxy that sent the request. If the engine cannot or chooses not to 
//	    resolve the hostname (to improve performance), this method returns the dotted-string form of the IP address. For HTTP servlets, 
//	    same as the value of the CGI variable REMOTE_HOST.
//
//	    Returns:
//	        a String containing the fully qualified name of the client
		return m_connectionsocket.getInetAddress().getHostName();
	}

	@Override //DONE
	public int getRemotePort() {
//	    Returns the Internet Protocol (IP) source port of the client or last proxy that sent the request.
//
//	    Returns:
//	        an integer specifying the port number
		return m_connectionsocket.getPort();
	}

	@Override //DONE
	public String getServerName() {
//	    Returns the host name of the server to which the request was sent. It is the value of the part before ":" in the Host header 
//	    value, if any, or the resolved server name, or the server IP address.
//
//	    Returns:
//	        a String containing the name of the server
		return m_connectionsocket.getLocalAddress().getHostName();
	}

	@Override //DONE
	public int getServerPort() {
//	    Returns the port number to which the request was sent. It is the value of the part after ":" in the Host header value, if any, 
//	    or the server port where the client connection was accepted on.
//
//	    Returns:
//	        an integer specifying the port number
		return m_connectionsocket.getLocalPort();
	}
	
	@Override //DONE
	public String getScheme() {
		// Should return "http".
		return "http";
	}

	@Override //DONE
	public boolean isSecure() {
//	    Returns a boolean indicating whether this request was made using a secure channel, such as HTTPS.
//
//	    Returns:
//	        a boolean indicating if the request was made using a secure channel
		return false;
	}

	@Override //DONE
	public void removeAttribute(String arg0) {
//	    Removes an attribute from this request. This method is not generally needed as attributes only persist as long as the request is 
//	    being handled.
//
//	    Attribute names should follow the same conventions as package names. Names beginning with java.*, javax.*, and com.sun.*, are 
//	    reserved for use by Sun Microsystems.
//
//	    Parameters:
//	        name - a String specifying the name of the attribute to remove
		m_props.remove(arg0);
	}

	@Override //DONE
	public void setAttribute(String arg0, Object arg1) {
//	    Stores an attribute in this request. Attributes are reset between requests. This method is most often used in conjunction with 
//	    RequestDispatcher.
//
//	    Attribute names should follow the same conventions as package names. Names beginning with java.*, javax.*, and com.sun.*, are 
//	    reserved for use by Sun Microsystems.
//	    If the object passed in is null, the effect is the same as calling removeAttribute(java.lang.String).
//	    It is warned that when the request is dispatched from the servlet resides in a different web application by RequestDispatcher, 
//	    the object set by this method may not be correctly retrieved in the caller servlet.
//
//	    Parameters:
//	        name - a String specifying the name of the attribute
//	        o - the Object to be stored
		if (arg1 == null)
			removeAttribute(arg0);
		else
			m_props.put(arg0, arg1);
	}

	@Override //DONE
	public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException {
//	    Overrides the name of the character encoding used in the body of this request. This method must be called prior to 
//		reading request parameters or reading input using getReader().
//
//	    Parameters:
//	        env - a String containing the name of the character encoding. 
//	    Throws:
//	        java.io.UnsupportedEncodingException - if this is not a valid encoding
		char_encoding = arg0;
	}
	
	@Override //DONE
	public BufferedReader getReader() throws IOException {
//	    Retrieves the body of the request as character data using a BufferedReader. The reader translates the character data according 
//	    to the character encoding used on the body. Either this method or getInputStream() may be called to read the body, not both.
//
//	    Returns:
//	        a BufferedReader containing the body of the request 
//	    Throws:
//	        UnsupportedEncodingException - if the character set encoding used is not supported and the text cannot be decoded 
//	        java.lang.IllegalStateException - if getInputStream() method has been called on this request 
//	        java.io.IOException - if an input or output exception occurred
		return new BufferedReader(new InputStreamReader(m_connectionsocket.getInputStream(), getCharacterEncoding()));
	}
	
	@Override //DONE
	public String getPathTranslated() {
		return null;
	}
	
	@Override //DONE
	public Principal getUserPrincipal() {
		return null;
	}
	
	@Override //DONE
	public boolean isUserInRole(String arg0) {
		return false;
	}
	
	@Override //DONE
	public RequestDispatcher getRequestDispatcher(String arg0) {
		return null;
	}
	
	@Override //DONE
	public ServletInputStream getInputStream() throws IOException {
		return null;
	}
	
	@Override //DONE
	public Enumeration<?> getLocales() {
		return null;
	}
	
	@Override //DONE
	public boolean isRequestedSessionIdFromUrl() {
		// Deprecated. As of Version 2.1 of the Java Servlet API, use isRequestedSessionIdFromURL() instead.
		return false;
	}
	
	@Override //DONE
	public String getRealPath(String arg0) {
		// Deprecated. As of Version 2.1 of the Java Servlet API, use ServletContext.getRealPath(java.lang.String) instead.
		return null;
	}

}
